Overhaul spawnveg to use clone(2) and fix many related spawning bugs #888
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This commit is a rewrite of #881. The previous pull request didn't address lingering bugs with
E2BIG
handling and file descriptor leaks, proving unsatisfactory. After support for direct usage ofclone
was added tospawnveg
, the previous fixes for theposix_spawn
implementation wound up unused and were scrapped (although those changes do work just fine and can be readded if that's desirable).Alterations:
spawnveg
that creates a new process withclone(2)
outright. This method is generally faster than usingposix_spawn(3)
, and is also more portable (because Linux with musl libc and NetBSD both provideclone
, but notposix_spawn_file_actions_addtcsetpgrp_np
). This code was initially based on the_real_vfork
code previously removed in ef9a5c7 (unlikevfork(2)
, there is no problem with doing stuff prior toexecve
forclone
withCLONE_VM | CLONE_VFORK
).tcsetpgrp
viaposix_spawn_file_actions_addtcsetpgrp_np()
. This code was only ever used with glibc 2.35+. (Not only that, but the only other platform that ever considered implementing a similar function was NetBSD1, where it appears to have been abandoned. This is ironic considering ksh no longer usesposix_spawn
on NetBSD as of this commit.) This code may be worth revisiting ifio_uring_spawn()
2 is ever actualized (that project appears to be rather inactive though).Demonstration of the (small) performance improvement garnered from using
clone
directly rather than viaposix_spawn
:spawnveg
. This is the primary cause of a lockup in the pty tests which can be reproduced as follows:The correct way to go about dealing with
SIGT*
is to set those toSIG_DFL
in the child process3.tcsetpgrp
to thefork
fallback inspawnveg
. Some form of this appears to have already been attempted in AT&T olden times, but that old version was broken and needed bugfixes desperately.tcsetpgrp
, block the terminal signals in the parent process viasigcritical()
.fork
fallback forspawnveg
works correctly in interactive terminals, prefer that to thesh_fork()
codepath on operating systems withoutclone
support. Even though the underlying system call is still ultimatelyfork
, thesh_ntfork
codepath is faster than the traditionalsh_fork
codepath. Benchmark:spawnveg
implementations intospawnveg_fast
andspawnveg_slow
. Choose the appropriate one whenspawnveg
is called; this removes the need for the xec.c ifdef hackery.ntfork_tcpgrp
ifdefs from xec.c;spawnveg
can handle it by itself now.spawnveg_fast
andspawnveg_slow
innovation,spawnveg
now always has support forsetsid
. It'll fallback tofork()
ifPOSIX_SPAWN_SETSID
andclone()
aren't available.posix_spawn
version ofspawnveg
, the flags should be of the short type pursuant to the POSIX specification.pipe2
in thefork
fallback forspawnveg
when it's available to avoid twofcntl
syscalls.spawnveg
documentation to reflect the new changes._spawnveg()
: Restore the terminal process group immediately after any relevant failed spawn attempt, rather than only insh_ntfork()
.tcsetpgrp
placement.Reproducer that could cause ksh to prematurely exit (for Linux systems with glibc 2.35+):
path_spawn()
: Do not print an error message andlongjmp
away upon encounteringE2BIG
or some other error; let the calling functions take care of that.path_exec()
: Added handling forE2BIG
.sh_ntfork
to leak file descriptors upon encountering an error (re: 8f848bc). (This bug/regression was encountered after fixing the badtcsetpgrp
usage.) Reproducer:command
andcommand -x
.sigcritical()
nesting matches. The ksh2020 devs appeared to have been confused by this line of code, so some additional clarification explaining what it does should be helpful for posterity.&
operator.Footnotes
https://blog.netbsd.org/tnf/entry/gsoc_reports_make_system_31 ↩
https://lwn.net/Articles/908268/ ↩
cf.
_sh_fork()
↩